package com.ruoyi.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.ruoyi.common.config.DroolsConfig;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.opio.util.ExampleBase;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.domain.SysDangerUnit;
import com.ruoyi.system.domain.vo.SysDangerPointVO;
import com.ruoyi.system.domain.vo.SysProductionPointVO;
import com.ruoyi.system.entity.SysDangerPoint;
import com.ruoyi.system.entity.SysMonitor;
import com.ruoyi.system.entity.SysProductionPoint;
import com.ruoyi.system.mapper.SysDangerUnitMapper;
import com.ruoyi.system.mapper.SysProductionPointMapper;
import com.ruoyi.system.service.SysMonitorService;
import com.ruoyi.system.service.SysProductionPointService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.utils.KieHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import javax.annotation.Resource;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 生产实时点位(SysProductionPoint)表服务实现类
 *
 * @author makejava
 * @since 2023-06-01 14:03:46
 */
@Service("sysProductionPointService")
public class SysProductionPointServiceImpl implements SysProductionPointService {
    @Resource
    private SysProductionPointMapper sysProductionPointMapper;

    @Resource
    private KieContainer kieContainer;

    @Autowired
    private Configuration configuration;

    @Autowired
    private DroolsConfig droolsConfig;

    @Resource
    private SysMonitorService sysMonitorService;

    public static final String FileName = "/SysProductionPoint.drl";

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public SysProductionPoint queryById(Integer id) {
        return this.sysProductionPointMapper.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param sysProductionPoint 筛选条件
     * @return 查询结果
     */
    @Override
    public List<SysProductionPoint> queryByPage(SysProductionPoint sysProductionPoint) {
        List<SysProductionPoint> sysProductionPoints = this.sysProductionPointMapper.queryAllByLimit(sysProductionPoint);
        return sysProductionPoints;
    }

    /**
     * 新增数据
     *
     * @param sysProductionPoint 实例对象
     * @return 实例对象
     */
    @Override
    public SysProductionPoint insert(SysProductionPoint sysProductionPoint) {
        this.sysProductionPointMapper.insert(sysProductionPoint);
        return sysProductionPoint;
    }

    /**
     * 修改数据
     *
     * @param sysProductionPoint 实例对象
     * @return 实例对象
     */
    @Override
    public SysProductionPoint update(SysProductionPoint sysProductionPoint) {
        this.sysProductionPointMapper.update(sysProductionPoint);
        return this.queryById(sysProductionPoint.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.sysProductionPointMapper.deleteById(id) > 0;
    }

    @Override
    public String importExcel(List<SysProductionPoint> sysProductionPoints, boolean updateSupport, String operName) {
        if (StringUtils.isNull(sysProductionPoints) || sysProductionPoints.size() == 0) {
            throw new ServiceException("导入用户数据不能为空！");
        }
        sysProductionPointMapper.insertBatch(sysProductionPoints);
        return "成功";
    }


    public void reload() {
        KieHelper kieHelper = new KieHelper();
        kieHelper.addContent(FileUtil.readString(droolsConfig.getUrl() + FileName, Charset.forName("utf-8")), ResourceType.DRL);
        Results results = kieHelper.verify();
        if (results.hasMessages(Message.Level.ERROR)) {
            System.out.println(results.getMessages());
            throw new IllegalStateException("### errors ###");
        }
        kieContainer = kieHelper.getKieContainer();
        System.out.println("刷新文件");
    }

    // 生成规则文件
    @Async
    public void createDroolsFile() throws IOException, TemplateException {
        List<SysProductionPointVO> sysProductionPoints  = getDate();
        Template template = configuration.getTemplate("SysProductionPoint.ftl");
        Map<String,Object> map = new HashMap<>();
        map.put("SysProductionPointVOList",sysProductionPoints);
        FileOutputStream file = new FileOutputStream(droolsConfig.getUrl() + FileName);
        OutputStreamWriter out = new OutputStreamWriter(file, "utf-8");
        template.process(map,out);
        out.close();
        System.out.println("success");
        this.reload();
    }

    public List<SysProductionPointVO> getDate() {
        List<SysProductionPoint> sysProductionPoints  = sysProductionPointMapper.queryAll();
        List<SysProductionPointVO> sysProductionPointVOS = new ArrayList<>();
        for (SysProductionPoint i : sysProductionPoints) {
            SysProductionPointVO sysDangerPointVO = new SysProductionPointVO();
            BeanUtils.copyBeanProp(sysDangerPointVO,i);
            // 低低报
            String playItLow = i.getPlayItLow();
            playItLow = StringUtils.isNotEmpty(playItLow) ? playItLow.replace("/", "") : playItLow;
            sysDangerPointVO.setPlayItLow(StringUtils.isEmpty(playItLow) ? -1 : Double.valueOf(playItLow));
            // 低报
            String lowQuota = i.getLowQuota();
            lowQuota = StringUtils.isNotEmpty(lowQuota) ? lowQuota.replace("/", "") : lowQuota;
            sysDangerPointVO.setLowQuota(StringUtils.isEmpty(lowQuota) ? -1 : Double.valueOf(lowQuota));
            // 高报
            String highQuota = i.getHighQuota();
            sysDangerPointVO.setHighQuota(StringUtils.isEmpty(highQuota) ? -1 : Double.valueOf(highQuota));
            // 高高报
            String highAndMighty = i.getHighAndMighty();
            highAndMighty = StringUtils.isNotEmpty(highAndMighty) ? highAndMighty.replace("/", "") : highAndMighty;
            sysDangerPointVO.setHighAndMighty(StringUtils.isEmpty(highAndMighty) ? -1 : Double.valueOf(highAndMighty));
            sysDangerPointVO.setAlert(0);
            sysProductionPointVOS.add(sysDangerPointVO);
        }
        return sysProductionPointVOS;
    }


    // 定时查询实时数据，是否达到报警条件
    @Scheduled(cron = "0/60 * * * * ?")
    public void ScheduledDataAlert() {
        List<SysProductionPointVO> sysProductionPoints  = getDate();
        Map<String, Object> map = ExampleBase.toResult();
        if (CollUtil.isNotEmpty(map)) {
            sysProductionPoints.forEach(i -> {
                Object o = map.get(i.getDatabaseBitNumber());
                i.setAv(StringUtils.isEmpty(o.toString()) ? 0 : Double.valueOf(o.toString()));
                // 调用规则引擎判断
                KieSession kieSession = kieContainer.newKieSession();
                kieSession.insert(i);
                kieSession.fireAllRules();
                kieSession.dispose();
                if (i.getAlert() == 1) {
                    SysMonitor query = sysMonitorService.queryByDataBase(i.getDatabaseBitNumber());
                    if (query == null || !StringUtils.isEmpty(query.getMonitorEndTime())) {
                        if (query != null) {
                            if (!query.getMonitorLevel().equals(i.getAlertType())) {
                                query.setMonitorEndTime(DateUtil.now());
                                query.setMonitorState("已恢复");
                                sysMonitorService.update(query);
                            }
                        }
                        SysMonitor sysMonitor = new SysMonitor();
                        sysMonitor.setMonitorType("生产数据");
                        sysMonitor.setMonitorName(i.getDeviceName());
                        sysMonitor.setRealTimeDataAddress(i.getDatabaseBitNumber());
                        sysMonitor.setMonitorParam(i.getUnit());
                        sysMonitor.setMonitorLevel(i.getAlertType());
                        sysMonitor.setMonitorValue(i.getAv().toString());
                        sysMonitor.setMonitorConfirmState("未确认");
                        sysMonitor.setMonitorState("未恢复");
                        sysMonitor.setMonitorStartTime(DateUtil.now());
                        sysMonitorService.insert(sysMonitor);
                    }
                } else {
                    SysMonitor query = sysMonitorService.queryByDataBase(i.getDatabaseBitNumber());
                    if (query != null && StringUtils.isEmpty(query.getMonitorEndTime())) {
                        query.setMonitorEndTime(DateUtil.now());
                        query.setMonitorState("已恢复");
                        sysMonitorService.update(query);
                    }
                }
            });
        }
    }
}
